package com.longcai.fenzhuang.fuyou;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

public class FuiouRsaCipher {

	private static final String RSA_CIPHER_CHARSET = "UTF-8";

	static {
		try {
			java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param base64Rsa
	 * @param inputStr
	 * @return
	 */
	public static String sign2Base64(String base64PriRsa, String inputStr) {
		try {
			PrivateKey privateKey = genPrivateKey(base64PriRsa);
			Signature signature = Signature.getInstance("SHA1withRSA", "BC");
			signature.initSign(privateKey);
			signature.update(inputStr.getBytes(RSA_CIPHER_CHARSET));
			return Base64.encodeBase64String(signature.sign());
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa签名异常");
		}
	}

	/**
	 *
	 * @return
	 */
	public static boolean verifySign(String base64PubRsa, String src, String base64SignValue) {
		try {
 			PublicKey publicKey = genPublicKey(base64PubRsa);
			Signature signature = Signature.getInstance("SHA1withRSA", "BC");
			signature.initVerify(publicKey);
			signature.update(src.getBytes(RSA_CIPHER_CHARSET));
			return signature.verify(Base64.decodeBase64(base64SignValue));
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa验证签名异常");
		}
	}

	private static PrivateKey genPrivateKey(String base64Rsa) {
		try {
			KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64Rsa));
			return kf.generatePrivate(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("初始化秘钥异常");
		}
	}

	private static PublicKey genPublicKey(String base64Rsa) {
		try {
			KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(base64Rsa));
			return kf.generatePublic(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("初始化秘钥失败");
		}
	}

	public static String encryptByRsaPub(String src, String base64PubRsa) {
		try {
			PublicKey publicKey = genPublicKey(base64PubRsa);
			byte[] encryptBytes = encryptByPublicKey(src.getBytes(RSA_CIPHER_CHARSET), publicKey);
			return Base64.encodeBase64String(encryptBytes);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa加密失败");
		}
	}

	public static String decryptByRsaPri(String base64Src, String base64PriRsa) {
		try {
			PrivateKey privateKey = genPrivateKey(base64PriRsa);
			return new String(decryptPrivateKey(Base64.decodeBase64(base64Src), privateKey), RSA_CIPHER_CHARSET);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa解密失败");
		}
	}

	/**
	 * 公钥加密
	 */
	private static byte[] encryptByPublicKey(byte[] srcData, PublicKey publicKey) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			// 分段加密
			int blockSize = cipher.getOutputSize(srcData.length) - 11;
			byte[] encryptedData = null;
			for (int i = 0; i < srcData.length; i += blockSize) {
				// 注意要使用2的倍数，否则会出现加密后的内容再解密时为乱码
				byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
				encryptedData = addAll(encryptedData, doFinal);
			}
			return encryptedData;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 私钥算法
	 * 
	 * @param srcData
	 *            源字节
	 * @param privateKey
	 *            私钥
	 * @param mode
	 *            加密 OR 解密
	 * @return
	 */
	private static byte[] decryptPrivateKey(byte[] srcData, PrivateKey privateKey) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			// 分段加密
			int blockSize = cipher.getOutputSize(srcData.length);
			byte[] decryptData = null;

			for (int i = 0; i < srcData.length; i += blockSize) {
				byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));

				decryptData = addAll(decryptData, doFinal);
			}
			return decryptData;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;

		if (newSize <= 0) {
			return new byte[0];
		}

		byte[] subarray = new byte[newSize];

		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);

		return subarray;
	}

	private static byte[] addAll(byte[] array1, byte[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		byte[] joinedArray = new byte[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	public static byte[] clone(byte[] array) {
		if (array == null) {
			return null;
		}
		return (byte[]) array.clone();
	}

	public static void main(String[] args) {
		String rsaPubBase64 = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI0wTj1wXcZCBSNrhx/qLvDb52p5mx9aH+lNPWUz9EPZRUA+gOhz9GJKt9vFWdg8UumB+rZlu16Ob1r+ZLGEtK+pU6mzhsXNUOALnIBUxaMTOmjV/HpWxaFk2IlfJ4JHrE7WZMP7MpvZpQWckNhUL+2VbbPHdJuwT9t5vTqKNdKfAgMBAAECgYAJolo0Zw5/ENI48IVv8BLz7I2F/nZPVV8IFHU0Cq+IUbMgByPUuNTcQCz7miPfVX5y4KOy/o4ijaWbl/BXDK8nk2/NaryLalMfbRk1pQHl7qq84nCLT2IPs2pTpSTDWRSccEoFBnbigXCd/4fXjZHRqMK2spOACfixs7T+LQStwQJBAMoR5sNjSquYnf1yHfhngnWQQQCIEcMs4rip813wjlVtfF+VHUttZ6iAcNaASCXiwvTsNQaHJ91rM8Zn8ze/G8UCQQCy3ssJNtI1fumoAQK/xXVOZiyTMpdK7m+W/+2Ba5cajFwHnW3fLKW/Y8/Xl0GPT4AeMddLkFYzex0k+2kYmOcTAkEAieKNROaMHWuW40rriIWZT/+PW31+IWCPlNLjbkan2UNMiyyFQOL2yNRcKwJ+ONvzjI1h4YJ4gW6Vdd2Y6YFOwQJANakrBiehJpVdaZ5sAbYuPAfhBYPe6YbgiU9cJEBvw3IqRcqP5K0TSHicKNRiwaibCfPv3+Z8RdOAadDWtZ9hawJATypfM2sODKzY/aZGejU7TESpCAOC8o3QD8lBCVRpHOgj2UGp98oAQ251tfW+CDXZ7umO2ODQL7ksFuGRIHcUsg==";
		/**
		* @Fields PRI_SIGN_KEY : 私钥
		*/
		String rsaPriBase64 = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMU/yu6SBhYo2YRrU5J5Ets7UOEXgdqfkeAPDvV+XPWwQFKE5L+TiFgZC9la4iLJBMU0ewFb7sdzH9QVD2JFKdI0kBeYi/H1l3NipliPgIMO5OhC39B/7tc16W3tt0ks49SzjPwr+CVNBfwEqcN8Te1gXHO+wUqPQsfMEBGWyq+rAgMBAAECgYEAkPCgUI/ycwQPWdN3tJDM/1VlyBD69Uf97BOEnXX+HvclPL20TOW+8WVuJIg41PC7VaGLpWMFYX/B6piTFlXWNPrfwM9UWPCrhojsuwUPetCweGP0QvzMxKu+O5iFtciNZRPRNnhzvscLCCIc3AIQhW2os7tHxvfr5YRmkAjR4hkCQQDl6qHPIr/c6Ejw//tARITSqru6pV3dFzZSLhxLH2YiitiswsP60AaVNCC9LedVv2D5DBFFCqKelKv8tkQBXL+lAkEA26BqvWKqkPiSlhQg4QLIl1Xxq/bFU0ejZV9IOM3qoVSEB08w59fmscVuqGIHdcRVI1abiXIst9e9pEfT2WORDwJAGMvBP7Gjt5NlqngxBLFfEclQDcUf5mRGe351lrSAM2F+FMO8lyQwUY8ZqM12kYzeTH28rxGCkE/AbLTLiMoT8QJAamdKr1xI9JlpM0qnLzxRAHjD8CNLMHDJqchCzjp9DRJMMNpeAETqYIAdf3iW0qh+8vL3wdxN6/eayid+bJi/YwJBALYNG4klSl9ApSdqaxZTKDjwNIbfva2vk1bNPTZk24y1qXU42S/9Z3IrAKnggYFaBumCIOiiLhXIjaGlnNDunXw=";

//		String rsaPubBase64 = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKwHTjMXJhagjboA16YWMbQxUBHFP7bNdp0FZiwoVXBISwVN55nsMTjXZKAcc4r46Y5ehyczQJjsFA3xtiZT7osCAwEAAQ==";
//		String rsaPriBase64 = "MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEArAdOMxcmFqCNugDXphYxtDFQEcU/ts12nQVmLChVcEhLBU3nmewxONdkoBxzivjpjl6HJzNAmOwUDfG2JlPuiwIDAQABAkBWV/xaDF5jsQYxu8aBaFZeOPoVUUmfeRT1zwXvV/c6OVwWShmtcV5rA3pURp9wAKmBJqOrXMqgIq4LFlOTKp1RAiEA2QQXug5FuUq5PKWg3S20p7JIq4UQeRIzYfTXYdgN1J8CIQDK7mBYGquXKprSkwuBRMgpAO1N6aN43kvg24ow3iwSlQIgbYeQRhpv/F4HceGSeC9aT40++jqVntWd02HU1xBJorcCIAOd2/m1//jhuYCnPj0/jJGugoww7cjprVCEmSHl08NBAiAPPmtd7s+9aeg9v1bc6kLeSW96DPJJ9lpkP2iK7nREkg==";
//		String inputStr = "test验证rsa加密";
//		String sign = sign2Base64(rsaPriBase64, inputStr);
//		System.out.println("加密结果:" + sign);
//		boolean verifySign = verifySign(rsaPubBase64, inputStr, sign);
//		System.out.println("验签结果：" + verifySign);

		
//		genPrivateKey(rsaPriBase64);
//		System.out.println("==============================");
//		genPublicKey(rsaPubBase64);
		
		
		
//		String src = UUID.randomUUID().toString();
		//String src = "楼晶|J2900184379402|0002900F1766674|710501425540450248710101|兴业银行股份有限公司上海青浦支行|上海美问信息科技有限公司|216400100100058711|310108197411014820|2900|310105324509997|2025-01-26|上海美问信息科技有限公司|0.44";
		String src = "0002900F1001919|19920000370|04";
		System.out.println(src);
		String encode = "PKTAAHzbHiUp9CgAysHy/wRK5nWFEuMjonQZS7yU555nn3P82DEvTmgiP8X7vSsEGbytDcWeDbtforz5nqEnCM13vnWr5EYFMyiGFJQ9nTIdb/FfPh6Ut38UxLRfglS14Lgc52Bt8kLjJAZKfS0BTIa/t3Zlqm6083HTVVAY+tkD6UkVvO1VehVCGP07RUPikpwn0fiNEytbjdmkwKme+6yTHaxKKQeCMokIqd0mdYCuSE7ByvqrRrf9+Kku6ksMgdAYHGY0aM4jZiH0eg33gNp7JLYf+xz/H+ax6+S454rStNSHR7TJlnj5ummMW0Rhx71zwEtxg/9IjwqcVHLomQ==";
		System.out.println(encode);
		System.out.println("11111" + verifySign(rsaPubBase64, src, encode));
//		String encryptByRsaPub = encryptByRsaPub(src, rsaPubBase64);
//		System.out.println(encryptByRsaPub);
//		String decryptByRsaPri = decryptByRsaPri(encryptByRsaPub, rsaPriBase64);
//		System.out.println(decryptByRsaPri);

	}

}
